import logging
import smtplib
from email.mime.text import MIMEText
from email.mime.multipart import MIMEMultipart
from datetime import datetime, timedelta
import os
from typing import List, Dict

from app import db
from app.models import Alert, Article, SocialMediaPost, Keyword

class AlertManager:
    def __init__(self):
        self.logger = logging.getLogger(__name__)
        self.smtp_server = os.getenv('SMTP_SERVER', 'smtp.example.com')
        self.smtp_port = int(os.getenv('SMTP_PORT', 587))
        self.smtp_username = os.getenv('SMTP_USERNAME', '')
        self.smtp_password = os.getenv('SMTP_PASSWORD', '')
        self.sender_email = os.getenv('SENDER_EMAIL', 'alert@example.com')
    
    def check_alerts(self) -> List[Dict]:
        """
        检查所有预警规则，返回触发的预警
        
        Returns:
            触发的预警列表
        """
        try:
            # 获取所有预警规则
            alerts = Alert.query.all()
            
            # 存储触发的预警
            triggered_alerts = []
            
            for alert in alerts:
                # 检查是否触发预警
                is_triggered, trigger_info = self._check_alert_condition(alert)
                
                if is_triggered:
                    # 记录触发信息
                    triggered_info = {
                        'alert_id': alert.id,
                        'keyword': alert.keyword,
                        'threshold': alert.threshold,
                        'user_id': alert.user_id,
                        'email': alert.email if alert.email_notification else None,
                        'trigger_time': datetime.now().isoformat(),
                        'trigger_info': trigger_info
                    }
                    
                    triggered_alerts.append(triggered_info)
                    
                    # 如果需要发送邮件通知
                    if alert.email_notification and alert.email:
                        self._send_alert_email(alert, trigger_info)
            
            return triggered_alerts
            
        except Exception as e:
            self.logger.error(f"检查预警失败: {str(e)}")
            return []
    
    def _check_alert_condition(self, alert: Alert) -> tuple:
        """
        检查预警条件是否满足
        
        Args:
            alert: 预警规则
            
        Returns:
            (是否触发, 触发信息)
        """
        try:
            # 获取最近24小时的数据
            start_time = datetime.now() - timedelta(hours=24)
            
            # 查询包含关键词的文章
            articles = Article.query.filter(
                Article.keywords.like(f'%{alert.keyword}%'),
                Article.collected_at >= start_time
            ).all()
            
            # 查询包含关键词的社交媒体帖子
            social_posts = SocialMediaPost.query.filter(
                SocialMediaPost.keywords.like(f'%{alert.keyword}%'),
                SocialMediaPost.collected_at >= start_time
            ).all()
            
            # 计算总数
            total_count = len(articles) + len(social_posts)
            
            # 检查是否超过阈值
            if total_count >= alert.threshold:
                # 获取情感分布
                sentiment_counts = {'正面': 0, '负面': 0, '中性': 0}
                
                for article in articles:
                    sentiment = article.sentiment or '中性'
                    sentiment_counts[sentiment] += 1
                
                for post in social_posts:
                    sentiment = post.sentiment or '中性'
                    sentiment_counts[sentiment] += 1
                
                # 构建触发信息
                trigger_info = {
                    'total_count': total_count,
                    'article_count': len(articles),
                    'social_post_count': len(social_posts),
                    'sentiment_distribution': sentiment_counts,
                    'recent_items': [
                        {
                            'title': article.title,
                            'source': article.source,
                            'url': article.url,
                            'sentiment': article.sentiment,
                            'time': article.collected_at.isoformat()
                        } for article in articles[:5]  # 只取前5篇文章
                    ] + [
                        {
                            'content': post.content[:100] + '...' if len(post.content) > 100 else post.content,
                            'platform': post.platform,
                            'url': post.url,
                            'sentiment': post.sentiment,
                            'time': post.collected_at.isoformat()
                        } for post in social_posts[:5]  # 只取前5条帖子
                    ]
                }
                
                return True, trigger_info
            
            return False, None
            
        except Exception as e:
            self.logger.error(f"检查预警条件失败: {str(e)}")
            return False, None
    
    def _send_alert_email(self, alert: Alert, trigger_info: Dict) -> bool:
        """
        发送预警邮件
        
        Args:
            alert: 预警规则
            trigger_info: 触发信息
            
        Returns:
            是否发送成功
        """
        try:
            # 创建邮件
            msg = MIMEMultipart()
            msg['From'] = self.sender_email
            msg['To'] = alert.email
            msg['Subject'] = f'舆情监控系统预警: 关键词 "{alert.keyword}" 触发阈值'
            
            # 构建邮件内容
            body = f"""
            <html>
            <body>
                <h2>舆情监控系统预警通知</h2>
                <p>您设置的关键词 <strong>"{alert.keyword}"</strong> 已触发预警阈值。</p>
                
                <h3>预警详情:</h3>
                <ul>
                    <li>关键词: {alert.keyword}</li>
                    <li>阈值: {alert.threshold}</li>
                    <li>触发时间: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}</li>
                    <li>24小时内相关内容总数: {trigger_info['total_count']}</li>
                    <li>其中文章数: {trigger_info['article_count']}</li>
                    <li>其中社交媒体帖子数: {trigger_info['social_post_count']}</li>
                </ul>
                
                <h3>情感分布:</h3>
                <ul>
                    <li>正面: {trigger_info['sentiment_distribution']['正面']}</li>
                    <li>负面: {trigger_info['sentiment_distribution']['负面']}</li>
                    <li>中性: {trigger_info['sentiment_distribution']['中性']}</li>
                </ul>
                
                <h3>最近相关内容:</h3>
            """
            
            # 添加最近内容
            for item in trigger_info['recent_items'][:5]:  # 只显示前5条
                if 'title' in item:  # 文章
                    body += f"""
                    <div style="margin-bottom: 10px; padding: 10px; border: 1px solid #ddd;">
                        <p><strong>标题:</strong> {item['title']}</p>
                        <p><strong>来源:</strong> {item['source']}</p>
                        <p><strong>情感:</strong> {item['sentiment']}</p>
                        <p><strong>时间:</strong> {item['time']}</p>
                        <p><a href="{item['url']}" target="_blank">查看原文</a></p>
                    </div>
                    """
                else:  # 社交媒体帖子
                    body += f"""
                    <div style="margin-bottom: 10px; padding: 10px; border: 1px solid #ddd;">
                        <p><strong>内容:</strong> {item['content']}</p>
                        <p><strong>平台:</strong> {item['platform']}</p>
                        <p><strong>情感:</strong> {item['sentiment']}</p>
                        <p><strong>时间:</strong> {item['time']}</p>
                        <p><a href="{item['url']}" target="_blank">查看原文</a></p>
                    </div>
                    """
            
            body += """
                <p>请登录舆情监控系统查看更多详情。</p>
            </body>
            </html>
            """
            
            msg.attach(MIMEText(body, 'html'))
            
            # 发送邮件
            if self.smtp_username and self.smtp_password:
                server = smtplib.SMTP(self.smtp_server, self.smtp_port)
                server.starttls()
                server.login(self.smtp_username, self.smtp_password)
                server.send_message(msg)
                server.quit()
                
                self.logger.info(f"已发送预警邮件到 {alert.email}")
                return True
            else:
                self.logger.warning("未配置SMTP服务器，无法发送邮件")
                return False
            
        except Exception as e:
            self.logger.error(f"发送预警邮件失败: {str(e)}")
            return False
    
    def create_alert(self, user_id: int, keyword: str, threshold: int, email_notification: bool = False, email: str = None) -> Dict:
        """
        创建预警规则
        
        Args:
            user_id: 用户ID
            keyword: 关键词
            threshold: 阈值
            email_notification: 是否发送邮件通知
            email: 通知邮箱
            
        Returns:
            创建结果
        """
        try:
            # 检查是否已存在相同的预警规则
            existing = Alert.query.filter_by(user_id=user_id, keyword=keyword).first()
            if existing:
                return {'success': False, 'message': '已存在相同的预警规则'}
            
            # 创建新预警规则
            alert = Alert(
                keyword=keyword,
                threshold=threshold,
                email_notification=email_notification,
                email=email,
                user_id=user_id
            )
            
            db.session.add(alert)
            db.session.commit()
            
            return {
                'success': True,
                'alert_id': alert.id,
                'message': '预警规则创建成功'
            }
            
        except Exception as e:
            db.session.rollback()
            self.logger.error(f"创建预警规则失败: {str(e)}")
            return {'success': False, 'message': f'创建预警规则失败: {str(e)}'}
    
    def delete_alert(self, alert_id: int, user_id: int) -> Dict:
        """
        删除预警规则
        
        Args:
            alert_id: 预警规则ID
            user_id: 用户ID
            
        Returns:
            删除结果
        """
        try:
            # 查找预警规则
            alert = Alert.query.filter_by(id=alert_id, user_id=user_id).first()
            
            if not alert:
                return {'success': False, 'message': '预警规则不存在或无权限删除'}
            
            # 删除预警规则
            db.session.delete(alert)
            db.session.commit()
            
            return {'success': True, 'message': '预警规则删除成功'}
            
        except Exception as e:
            db.session.rollback()
            self.logger.error(f"删除预警规则失败: {str(e)}")
            return {'success': False, 'message': f'删除预警规则失败: {str(e)}'}
    
    def get_user_alerts(self, user_id: int) -> List[Dict]:
        """
        获取用户的预警规则
        
        Args:
            user_id: 用户ID
            
        Returns:
            预警规则列表
        """
        try:
            # 查询用户的预警规则
            alerts = Alert.query.filter_by(user_id=user_id).all()
            
            # 转换为字典列表
            result = []
            for alert in alerts:
                result.append({
                    'id': alert.id,
                    'keyword': alert.keyword,
                    'threshold': alert.threshold,
                    'email_notification': alert.email_notification,
                    'email': alert.email,
                    'created_at': alert.created_at.isoformat()
                })
            
            return result
            
        except Exception as e:
            self.logger.error(f"获取用户预警规则失败: {str(e)}")
            return [] 